﻿using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using ShenNius.Caches;
using ShenNius.Repository;
using ShenNius.Sys.API.Domain.Entity;
using ShenNius.Sys.API.Domain.Repository;
using ShenNius.Sys.API.Domain.Service;
using ShenNius.Sys.API.Dtos.Common;
using ShenNius.Sys.API.Dtos.Input;
using ShenNius.Sys.API.Dtos.Output;
using ShenNius.Sys.API.Infrastructure;
using ShenNius.Sys.API.Infrastructure.Attributes;
using ShenNius.Sys.API.Infrastructure.Common;
using ShenNius.Sys.API.Infrastructure.Configs;
using ShenNius.Sys.API.Jwt;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace ShenNius.Sys.API.Controllers
{/// <summary>
 /// 用户控制器
 /// </summary>
    public class UserController : ApiControllerBase
    {
        private readonly JwtHelper _jwtHelper;
        private readonly IBaseRepository<User> _userRepository;
        private readonly IBaseRepository<R_User_Role> _r_User_RoleRepository;
        private readonly IMenuRepository _menuRepository;
        private readonly IDistributedCache _cacheHelper;
        private readonly ICurrentUserContext _currentUserContext;
        private readonly IMapper _mapper;
        private readonly LoginDomainService _loginDomainService;
        private readonly IRecycleRepository _recycleRepository;
        public const string loginRSACrypt = "loginRSACrypt";

        /// <summary>
        /// 
        /// </summary>
        /// <param name="jwtHelper"></param>
        /// <param name="userRepository"></param>
        /// <param name="r_User_RoleRepository"></param>
        /// <param name="menuRepository"></param>
        /// <param name="cacheHelper"></param>
        /// <param name="currentUserContext"></param>
        /// <param name="mapper"></param>
        /// <param name="loginDomainService"></param>
        /// <param name="recycleRepository"></param>
        public UserController(JwtHelper jwtHelper, IBaseRepository<User> userRepository, IBaseRepository<R_User_Role> r_User_RoleRepository, IMenuRepository menuRepository, IDistributedCache cacheHelper, ICurrentUserContext currentUserContext, IMapper mapper, LoginDomainService loginDomainService, IRecycleRepository recycleRepository)
        {
            _jwtHelper = jwtHelper;
            _userRepository = userRepository;
            _r_User_RoleRepository = r_User_RoleRepository;
            _menuRepository = menuRepository;
            _cacheHelper = cacheHelper;
            _currentUserContext = currentUserContext;
            _mapper = mapper;
            _loginDomainService = loginDomainService;
            _recycleRepository = recycleRepository;
        }

        [HttpGet, AllowAnonymous]
        public IActionResult RemoveMenuCache(int userId)
        {
            //由于使用了匿名访问，必须前台传值用户id进来，后台拿不到用户当前的值。
            //IMenuService:LoadLeftMenuTreesAsync:[1]  清理左侧树形菜单缓存
            _cacheHelper.Remove($"IMenuService:LoadLeftMenuTreesAsync:[{userId}]");
            return Ok(new { code = 1, msg = "服务端成功清理左侧树形菜单缓存" });
        }
        /// <summary>
        /// 用户注册
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost, Authority]
        public async Task<ApiResult> Add([FromBody] UserRegisterInput input)
        {
            var model = await _userRepository.GetModelAsync(d => !d.IsDeleted && d.Name.Equals(input.Name));
            if (model != null && model.Id > 0)
            {
                return new ApiResult($"已经存在[{input.Name}]该用户名了");
            }
            var userModel = _mapper.Map<User>(input);

            userModel.ChangePassword(input.Password);
            userModel.ModifyIpAddress();
            var i = await _userRepository.AddAsync(userModel);
            return i > 0 ? new ApiResult(i) : new ApiResult("用户添加失败！");
        }

        [HttpPost, Authority]
        public async Task<ApiResult> Modify([FromBody] UserModifyInput input)
        {
            var isExistModel = await _userRepository.GetModelAsync(d => !d.IsDeleted && d.Id != input.Id && d.Name.Equals(input.Name));
            if (isExistModel != null && isExistModel.Id > 0)
            {
                return new ApiResult($"已经存在[{input.Name}]该用户名了");
            }
            var model = await _userRepository.GetModelAsync(d => d.Id == input.Id && d.IsDeleted == false);
            if (!model.Password.Equals(input.Password))
            {
                model.ChangePassword(input.Password);
            }
            model.Modify(input.Name, input.Mobile, input.Remark, input.Email, input.TrueName, input.Sex);
            var i = await _userRepository.UpdateAsync(model);

            return i > 0 ? new ApiResult(i) : new ApiResult("用户修改失败！");
        }

        [HttpDelete, Authority]
        public async Task<ApiResult> Deletes([FromBody] DeletesInput input)
        {
            return new ApiResult(await _userRepository.DeleteAsync(input.Ids));
        }
        [HttpPost]
        public async Task<ApiResult> ModfiyPwd([FromBody] ModifyPwdInput input)
        {
            input.ModifyPassword(_currentUserContext.Id);
            var model = await _userRepository.GetModelAsync(d => d.Id == input.Id && d.IsDeleted == false);
            if (model.Id <= 0)
            {
                throw new ArgumentException("用户信息为空");
            }
            if (model.Password == input.OldPassword)
            {
                throw new ArgumentNullException("旧密码错误!");
            }
            model.IsEquaPassword(input.OldPassword);
            model.ChangePassword(input.ConfirmPassword);
            var i = await _userRepository.UpdateAsync(model);
            return i > 0 ? new ApiResult(i) : new ApiResult("用户密码修改失败！");
        }
        [HttpGet]
        public async Task<ApiResult> GetUser(int id)
        {
            var model = await _userRepository.GetModelAsync(d => d.Id == id);
            var data = _mapper.Map<UserOutput>(model);
            return new ApiResult(data);
        }
        /// <summary>
        /// 查询列表
        /// </summary>
        /// <returns></returns>
        [HttpGet, Authority(Action = nameof(Button.Auth))]
        public async Task<ApiResult> GetListPages(int page, string key)
        {
            Expression<Func<User, bool>> whereExpression = d => !d.IsDeleted;
            if (!string.IsNullOrEmpty(key))
            {
                whereExpression = d => d.Name.Contains(key) && !d.IsDeleted;
            }
            var res = await _userRepository.GetPagesAsync(page, 15, whereExpression, d => d.Id, false);
            return new ApiResult(data: new { count = res.TotalItems, items = res.Items });
        }
        /// <summary>
        /// 设置角色（授权）
        /// </summary>
        /// <returns></returns>
        [HttpPost, Authority(Action = nameof(Button.Auth))]
        public async Task<ApiResult> SetRole([FromBody] SetUserRoleInput input)
        {
            //分配角色
            int i = 0;
            if (input.Status)
            {
                var model = await _r_User_RoleRepository.GetModelAsync(d => d.UserId == input.UserId && d.RoleId == input.RoleId && d.IsDeleted == false);
                if (model.Id > 0)
                {
                    return new ApiResult("已经存在该角色了", 500);
                }
                R_User_Role addModel = R_User_Role.Create(input.UserId, input.RoleId);
                i = await _r_User_RoleRepository.AddAsync(addModel);
                return i > 0 ? new ApiResult(i) : new ApiResult("用户角色关联失败！");
            }
            else
            {
                i = await _r_User_RoleRepository.UpdateAsync(d => new R_User_Role { DeleteTime = DateTime.Now, IsDeleted = true }, d => d.UserId == input.UserId && d.RoleId == input.RoleId);
                // await DeleteAsync(d => d.UserId == input.UserId && d.RoleId == input.RoleId);
                //删除的话 要把授权的权限都要删除掉 风险比较高。
                return i > 0 ? new ApiResult(i) : new ApiResult("用户角色状态设置失败！");
            }
        }

        [HttpGet]
        [AllowAnonymous]
        public ApiResult LoadLoginInfo()
        {
            var rsaKey = RSACrypt.GetKey();
            var number = Guid.NewGuid().ToString();
            if (rsaKey.Count <= 0 || rsaKey == null)
            {
                throw new ArgumentNullException("获取登录的公钥和私钥为空");
            }
            //获得公钥和私钥
            _cacheHelper.Set(SysCacheKey.loginRSACrypt + number, rsaKey);
            return new ApiResult(data: new { RsaKey = rsaKey, Number = number });
        }
        /// <summary>
        ///用户前后端分离的登录
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public async Task<ApiResult<LoginOutput>> SignIn([FromBody] LoginInput loginInput)
        {
            var rsaKey = _cacheHelper.Get<List<string>>(SysCacheKey.loginRSACrypt + loginInput.NumberGuid);
            if (rsaKey == null)
            {
                return new ApiResult<LoginOutput>("登录失败，请刷新浏览器再次登录!");
            }
            //Ras解密密码
            var ras = new RSACrypt(rsaKey[0], rsaKey[1]);
            loginInput.Password = ras.Decrypt(loginInput.Password);
            var result = await _loginDomainService.LoginAsync(loginInput);
            var token = _jwtHelper.GetJwtToken(result.Data);
            if (string.IsNullOrEmpty(token))
            {
                return new ApiResult<LoginOutput>("生成的token字符串为空!");
            }
            result.Data.Token = token;
            return result;
        }

        [HttpDelete, Authority(Action = nameof(Button.Delete))]
        public virtual Task<ApiResult> SoftDelete([FromBody] DeletesInput deleteInput)
        {
            return _recycleRepository.SoftDeleteAsync(deleteInput, _userRepository);
        }


    }
}
